package capricornus.components.tooltips
{
	import capricornus.components.ComponentsManager;
	import capricornus.core.StageManager;
	import capricornus.utils.SpriteUtils;
	
	import flash.display.Bitmap;
	import flash.display.DisplayObject;
	import flash.display.InteractiveObject;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Rectangle;
	import flash.utils.Dictionary;

	public class ToolTips
	{
		private static var _ins:ToolTips = null;
		
		private var _dict:Dictionary;
		private var _dictRenderDis:Dictionary;
		private var _render:ToolTipRender;
		
		private var _hasAddMoveEvent:Boolean = false;
		private var _currentOverDis:InteractiveObject;
		
		public function ToolTips()
		{
			init();
		}
		
		private static function get instance():ToolTips
		{
			if( null==_ins )
			{
				_ins = new ToolTips();
			}
			return _ins;
		}
		
		private function init():void
		{
			_dict = new Dictionary();
			_dictRenderDis = new Dictionary();
			_render = new ToolTipRender();
			
			StageManager.stage.addEventListener( Event.DEACTIVATE, onDeactivate, false, 0, true );
		}
		
		private function onDeactivate( e:Event ):void
		{
		}
		
		public static function set toolTipRender( render:ToolTipRender ):void
		{
			instance._render = render;
		}
		
		public static function addTips( dis:InteractiveObject, data:ToolTipVO ):void
		{
			instance.addTips( dis, data );
		}
		
		public static function removeTips( dis:InteractiveObject ):void
		{
			instance.removeTips( dis );
		}
		
		public function addTips( dis:InteractiveObject, data:ToolTipVO ):void
		{
			if( _dict[dis]==null )
			{
				if( data==null ) data = new ToolTipVO();
				_dict[dis] = data;
				
				dis.addEventListener( Event.REMOVED_FROM_STAGE, onRemoveFromStage, false, 0, true );
				dis.addEventListener( MouseEvent.ROLL_OVER, onMouseOver, false, 0, true );
				dis.addEventListener( MouseEvent.MOUSE_MOVE, onMouseMove, false, 0, true );
				dis.addEventListener( MouseEvent.ROLL_OUT, onMouseOut, false, 0, true );
			}
		}
		
		public function removeTips( dis:InteractiveObject ):void
		{
			var data:Object = _dict[dis];
			if( data != null )
			{
				delete _dict[dis];
				
				var s:DisplayObject = _dictRenderDis[dis];
				if( s != null )
				{
					if( s.parent != null ) s.parent.removeChild( s );
				}
				
				dis.removeEventListener( Event.REMOVED_FROM_STAGE, onRemoveFromStage );
				dis.removeEventListener( MouseEvent.ROLL_OVER, onMouseOver );
				dis.removeEventListener( MouseEvent.MOUSE_MOVE, onMouseMove );
				dis.removeEventListener( MouseEvent.ROLL_OUT, onMouseOut );
			}
		}
		
		private function onRemoveFromStage( e:Event ):void
		{
			var dis:InteractiveObject = e.currentTarget as InteractiveObject;
			
			var s:DisplayObject = _dictRenderDis[dis];
			if( s != null )
			{
				delete _dictRenderDis[dis];
				
				if( s.parent != null )
				{
					s.parent.removeChild( s );
				}
			}
		}
		
		private function onMouseOver( e:MouseEvent ):void
		{
			var dis:InteractiveObject = e.currentTarget as InteractiveObject;
			
			var s:DisplayObject = _dictRenderDis[dis];
			if( s==null )
			{
				s = _render.getTips( _dict[dis].data );
				if( s==null ) return;
				
				_dictRenderDis[dis] = s;
				ComponentsManager.instance.tipLayer.addChild( s );
				
				setTipsPos( s, e );
			}
		}
		
		private function onMouseMove( e:MouseEvent ):void
		{
			var dis:InteractiveObject = e.currentTarget as InteractiveObject;
			
			var s:DisplayObject = _dictRenderDis[dis];
			if( s != null )
			{
				setTipsPos( s, e );
			}
		}
		
		private function setTipsPos( s:DisplayObject, e:MouseEvent ):void
		{
			s.x = int(e.stageX);
			if( s.x + s.width > StageManager.stageWidth )
			{
				s.x = int(s.x - s.width);
			}
			s.y = int(e.stageY);
			if( s.y + s.height > StageManager.stageHeight )
			{
				s.y = int(s.y - s.height);
			}
		}
		
		private function onMouseOut( e:MouseEvent ):void
		{
			var dis:InteractiveObject = e.currentTarget as InteractiveObject;
			
			var s:DisplayObject = _dictRenderDis[dis];
			if( s != null )
			{
				delete _dictRenderDis[dis];
				
				if( s.parent != null )
				{
					clearSprite( s );
					s.parent.removeChild( s );
				}
			}
		}
		
		private function clearSprite( dis:DisplayObject ):void
		{
			var s:Sprite = dis as Sprite;
			if( s != null )
			{
				while( s.numChildren > 0 ) 
				{
					var dis:DisplayObject = s.removeChildAt(0);
					if( dis is Bitmap )
					{
						(dis as Bitmap).bitmapData = null;
					}
				}
			}
			var bm:Bitmap = dis as Bitmap;
			if( bm != null )
			{
				bm.bitmapData = null;
			}
		}
	}
}